﻿using AntDesign.JsInterop;
using AntDesign.TableModels;
using Microsoft.AspNetCore.Components.Web;
using System.Collections.Concurrent;
using System.Runtime.CompilerServices;

namespace Xms.Abp.Components;

public partial class PagingListViewBase<TService, TPagingListViewModel, TKey, TPagedParameter, TDetailsViewModel, TCreateViewModel, TUpdateViewModel, TDetailsView, TCreateView, TUpdateView, TSelf> : AntDomComponentBase
    where TService : CrudService<TPagingListViewModel, TKey, TPagedParameter, TDetailsViewModel, TCreateViewModel, TUpdateViewModel>
    where TPagingListViewModel : class, IEntityResult<TKey>, new()
    where TDetailsViewModel : class, new()
    where TPagedParameter : class, IPagedSortedAndFilterParameter, new()
    where TDetailsView : DetailsViewBase<TKey>
    where TCreateView : DetailsViewBase<TKey>
    where TUpdateView : DetailsViewBase<TKey>
    where TSelf: PagingListViewBase<TService, TPagingListViewModel, TKey, TPagedParameter, TDetailsViewModel, TCreateViewModel, TUpdateViewModel, TDetailsView, TCreateView, TUpdateView, TSelf>
    where TKey : struct
{
    [Inject] public InteropService JS { get; set; }
    [Parameter] public TPagedParameter PagedParameter { get; set; } = new();
    protected string CurrentSorting;
    protected int TotalCount;
    protected bool PagingLoading = false;
    public IEnumerable<TPagingListViewModel> SelectedRows;
    private IEnumerable<TPagingListViewModel> DataSource;

    [Inject] public DialogService DialogService { get; set; }
    [Inject] public TService AppService { get; set; }
    [Inject] public ConfirmService ConfirmService { get; set; }
    [Inject] public MessageService MessageService { get; set; }
    [Inject] public ICurrentUser CurrentUser { get; set; }

    #region Policy
    protected virtual string DetailsPolicyName => GetPolicy();
    protected virtual string CreatePolicyName => GetPolicy();
    protected virtual string UpdatePolicyName => GetPolicy();
    protected virtual string DeletePolicyName => GetPolicy();
    protected virtual string DeleteManyPolicyName => GetPolicy();
    protected virtual string ToggleEnablePolicyName => GetPolicy();
    protected virtual string ExportPolicyName => GetPolicy();
    protected virtual string ImportPolicyName => GetPolicy();
    protected virtual string ReviewPolicyName => GetPolicy();
    protected virtual string SubmitReviewPolicyName => GetPolicy();

    public bool HasDetailsPermission => HasPermission(DetailsPolicyName);
    public bool HasCreatePermission => HasPermission(CreatePolicyName);
    public bool HasUpdatePermission => HasPermission(UpdatePolicyName);
    public bool HasDeletePermission => HasPermission(DeletePolicyName);
    public bool HasDeleteManyPermission => HasPermission(DeleteManyPolicyName);
    public bool HasToggleEnablePermission => HasPermission(ToggleEnablePolicyName);
    public bool HasExportPermission => HasPermission(ExportPolicyName);
    public bool HasImportPermission => HasPermission(ImportPolicyName);
    public bool HasReviewPermission => HasPermission(ReviewPolicyName);
    public bool HasSubmitReviewPermission => HasPermission(SubmitReviewPolicyName);
    public bool HasPermission(string policyName)
    {
        if (CurrentUser.UserName == "admin" || policyName == null || Policies?.Children?.Any(r => r.Permission == policyName) != true)
        {
            return true;
        }
        return GrantedPolicyNames?.Contains(policyName) == true;
    }
    //[Inject] public IXmsAuthorizationService AuthorizationService { get; set; }
    //protected virtual async Task SetPermissionsAsync()
    //{
    //    GrantedPolicyNames.AddRange(await AuthorizationService.FilterGrantedAsync(Policies.Values));
    //}

    [Parameter] public PermissionItem Policies { get; set; }
    protected virtual List<string> GrantedPolicyNames { get; set; }

    protected virtual string GetPolicy([CallerMemberName] string memberName = null)
    {
        memberName = memberName.RemovePostFix("PolicyName").RemovePostFix("Async");
        return Policies?.Children?.FirstOrDefault(r => r.Permission == memberName)?.Permission;
    }
    protected virtual async Task CheckPolicyAsync(string policyName)
    {
        if (string.IsNullOrEmpty(policyName))
        {
            return;
        }
        if (!HasPermission(policyName))
        {
            throw new Exception("没有权限");
        }
        await Task.CompletedTask;
    }

    protected virtual async Task CheckDetailsPolicyAsync()
    {
        await CheckPolicyAsync(DetailsPolicyName);
    }
    protected virtual async Task CheckCreatePolicyAsync()
    {
        await CheckPolicyAsync(CreatePolicyName);
    }
    protected virtual async Task CheckUpdatePolicyAsync()
    {
        await CheckPolicyAsync(UpdatePolicyName);
    }
    protected virtual async Task CheckDeletePolicyAsync()
    {
        await CheckPolicyAsync(DeletePolicyName);
    }
    protected virtual async Task CheckDeleteManyPolicyAsync()
    {
        await CheckPolicyAsync(DeleteManyPolicyName);
    }
    protected virtual async Task CheckToggleEnablePolicyAsync()
    {
        await CheckPolicyAsync(ToggleEnablePolicyName);
    }
    protected virtual async Task CheckExportPolicyAsync()
    {
        await CheckPolicyAsync(ExportPolicyName);
    }
    protected virtual async Task CheckImportPolicyAsync()
    {
        await CheckPolicyAsync(ImportPolicyName);
    }
    #endregion

    [Parameter] public TCreateViewModel CreateInRowModel { get; set; }

    [Parameter] public TUpdateViewModel UpdateInRowModel { get; set; }

    [Parameter] public string ModuleName { get; set; }

    [Parameter] public string SubModuleName { get; set; }

    [Parameter] public string Title { get; set; }

    [Parameter] public string FunctionSimpleName { get; set; }

    private string ShowFunctionSimpleName
    {
        get
        {
            return FunctionSimpleName ?? Title?.RemovePostFix("管理");
        }
    }

    [Parameter] public bool Detailsable { get; set; }

    [Parameter] public Func<TPagingListViewModel, bool> DetailsableFunc { get; set; }

    [Parameter] public bool Creatable { get; set; }

    [Parameter] public bool CreateChildable { get; set; }

    [Parameter] public Func<TPagingListViewModel, bool> CreateChildableFunc { get; set; }

    [Parameter] public bool Updatable { get; set; }

    [Parameter] public Func<TPagingListViewModel, bool> UpdatableFunc { get; set; }

    [Parameter] public bool DeleteManyable { get; set; }

    [Parameter] public Func<IEnumerable<TPagingListViewModel>, bool> DeleteManyableFunc { get; set; }

    [Parameter] public bool Deletable { get; set; }

    [Parameter] public Func<TPagingListViewModel, bool> DeletableFunc { get; set; }

    [Parameter] public Func<TPagingListViewModel, bool> RowMoreActionsFunc { get; set; }

    [Parameter] public bool Exportable { get; set; }

    [Parameter] public bool Importable { get; set; }

    [Parameter] public bool Reviewable { get; set; }

    [Parameter] public Func<TPagingListViewModel, bool> ReviewableFunc { get; set; }

    [Parameter] public bool SubmitReviewable { get; set; }

    [Parameter] public Func<TPagingListViewModel, bool> SubmitReviewableFunc { get; set; }

    [Parameter] public bool DisableFilter { get; set; }

    [Parameter] public Func<RowData<TPagingListViewModel>, bool> RowExpandable { get; set; }

    [Parameter] public Func<TPagingListViewModel, IEnumerable<TPagingListViewModel>> TreeChildren { get; set; }
        = r => (r is IHasChildren<TPagingListViewModel> s ? s.Children : null) ?? Enumerable.Empty<TPagingListViewModel>();

    [Parameter] public RenderFragment<TPagedParameter> SearchContent { get; set; }

    [Parameter] public RenderFragment ToolborContent { get; set; }

    [Parameter] public RenderFragment<TPagingListViewModel> Columns { get; set; }

    [Parameter] public RenderFragment<RowData<TPagingListViewModel>> ExpandTemplate { get; set; }

    [Parameter] public RenderFragment ToolbarMoreActions { get; set; }

    [Parameter] public RenderFragment<TPagingListViewModel> RowMoreActions { get; set; }

    [Parameter] public Func<TPagedParameter, Task<PagedResult<TPagingListViewModel>>> SearchPageData { get; set; }

    [Parameter] public bool IsCustomRowActions { get; set; }

    [Parameter] public string ActionColumnWidth { get; set; } = "140";

    [Parameter] public string ScrollX { get; set; } = "1500";

    [Parameter] public int? DialogWidth { get; set; }

    [Parameter] public string SearchFilterPlaceholder { get; set; } = "模糊搜索内容";

    protected static ConcurrentDictionary<Type, TableColumnInfo[]> TypesColumns = new();

    protected TableColumnInfo[] GetTableColumnInfos()
    {
        return TypesColumns.GetOrAdd(typeof(TPagingListViewModel), XmsUIHelper.GetTableColumnInfos<TPagingListViewModel>());
    }

    public PagingListViewBase()
    {
    }

    protected override async Task OnInitializedAsync()
    {
        if (MenuDefinition.ContainsPermission(Title))
        {
            Policies = MenuDefinition.GetPermissionItem(Title);
            GrantedPolicyNames = CurrentUser.Permissions.ContainsKey(Policies?.Permission) ? CurrentUser.Permissions[Policies?.Permission] : null;
        }
        //Policies = Title == "租户管理" ? null : MenuDefinition.PermissionDictionary?[Title];
        //GrantedPolicyNames = CurrentUser.Permissions?.FirstOrDefault(r => r.ModuleName == Policies?.Permission)?.Items;

        await base.OnInitializedAsync();
    }

    protected virtual bool IsSelectionDisabled(TPagingListViewModel model)
    {
        return false;
    }

    protected async Task HandleTableChange(QueryModel<TPagingListViewModel> queryModel)
    {
        //Console.WriteLine("HandleTableChange" + DateTime.Now.Ticks);
        //if (PagedParameter.PageIndex != queryModel.PageIndex)
        //{

        //}
        PagedParameter.PageIndex = queryModel.PageIndex;
        PagedParameter.PageSize = queryModel.PageSize;
        await RefreshPagingListAsync();
    }

    public virtual async Task OnSearchClickAsync()
    {
        if (PagedParameter.PageIndex == 1)
        {
            await RefreshPagingListAsync();
        }
        else
        {
            PagedParameter.PageIndex = 1;
        }
    }

    protected async Task OnPagingChangeAsync(PaginationEventArgs args)
    {
        PagedParameter.PageIndex = args.Page;
        PagedParameter.PageSize = args.PageSize;
        //Console.WriteLine("OnPagingChangeAsync" + DateTime.Now.Ticks);
        //await RefreshPagingListAsync
        await Task.CompletedTask;
    }

    protected async Task OnGoClickAsync(MouseEventArgs args)
    {
        var pageIndexStr = await JS.JsInvokeAsync<string>("eval", "document.getElementsByClassName('ant-pagination-options-quick-jumper')[0].children[0].value");
        if (int.TryParse(pageIndexStr, out var pageIndex))
        {
            PagedParameter.PageIndex = pageIndex;
        }
    }

    public async Task RefreshPagingListAsync()
    {
        PagingLoading = true;
        var pageData = await AppService.GetListAsync(PagedParameter);
        if (pageData == null)
        {
            PagingLoading = false;
            return;
        }
        TotalCount = (int)pageData.TotalCount;
        DataSource = pageData.Items as List<TPagingListViewModel> ?? pageData.Items.ToList();
        PagingLoading = false;
    }

    protected Func<PaginationTotalContext, string> PagingShowTotal()
    {
        return ctx => $"共{ctx.Total}条";
    }

    protected async Task OnCreateActionClickAsync()
    {
        if (typeof(TPagingListViewModel).IsAssignableFrom(typeof(IEditingInRow)))
        {
            var row = new TPagingListViewModel();
            (row as IEditingInRow).IsCreating = true;
            DataSource ??= new List<TPagingListViewModel>();

            (DataSource as List<TPagingListViewModel>).Insert(0, row);

            return;
        }
        if (await DialogService.OpenCreateAsync<TCreateView, TKey>("创建" + ShowFunctionSimpleName, width: DialogWidth))
        {
            await MessageService.Success(ShowFunctionSimpleName + "创建成功！", 1.5);
            await RefreshPagingListAsync();
        }
    }

    protected async Task OnExportActionClickAsync()
    {
        if (TotalCount > 50000)
        {
            if (await ConfirmService.Show("当前查询数据大于50000条，无法全部导出，确认要导出前50000条吗？", "警告", confirmIcon: ConfirmIcon.Warning) == ConfirmResult.OK)
            {
                await AppService.ExportAsync(PagedParameter);
            }
        }
        else
        {
            await AppService.ExportAsync(PagedParameter);
        }
    }

    protected async Task OnDeleteManyActionClickAsync()
    {
        if (SelectedRows == null || SelectedRows.Count() == 0)
        {
            await MessageService.Error("请选择要删除的数据！", 1.5);
            return;
        }
        if (await ConfirmService.Show("确定要删除选中的这些数据吗？", "警告", confirmIcon: ConfirmIcon.Warning) == ConfirmResult.OK)
        {
            var ids = SelectedRows.Select(r => r.Id).ToArray();
            await AppService.DeleteManyAsync(ids);
            await MessageService.Success(ShowFunctionSimpleName + "删除成功！", 1.5);
            await RefreshPagingListAsync();
        }
    }

    protected async Task OnDownloadTemplateActionClickAsync()
    {
        await AppService.DownloadTemplateAsync();
    }

    protected async Task OnDetailsActionClickAsync(TPagingListViewModel model)
    {
        await DialogService.OpenDetailsAsync<TDetailsView, TKey>(ShowFunctionSimpleName + "详情", model.Id, model, width: DialogWidth);
    }

    protected async Task OnCreateActionClickAsync(TPagingListViewModel model)
    {
        if (await DialogService.OpenCreateAsync<TUpdateView, TKey>("创建" + ShowFunctionSimpleName, model.Id, model, width: DialogWidth))
        {
            await MessageService.Success(ShowFunctionSimpleName + "创建成功！", 1.5);
            await RefreshPagingListAsync();
        }
    }

    protected async Task OnUpdateActionClickAsync(TPagingListViewModel model)
    {
        if (model is IEditingInRow e)
        {
            e.IsUpdating = true;
            return;
        }
        if (await DialogService.OpenUpdateAsync<TUpdateView, TKey>(ShowFunctionSimpleName + "修改", model.Id, model, width: DialogWidth))
        {
            await MessageService.Success(ShowFunctionSimpleName + "修改成功！", 1.5);
            await RefreshPagingListAsync();
        }
    }

    protected async Task OnReviewActionClickAsync(TPagingListViewModel model)
    {
        if (await DialogService.OpenReviewAsync<TUpdateView, TKey>(ShowFunctionSimpleName + "审核", model.Id, model, width: DialogWidth))
        {
            await MessageService.Success(ShowFunctionSimpleName + "审核完成！", 1.5);
            await RefreshPagingListAsync();
        }
    }

    protected async Task OnSubmitReviewActionClickAsync(TPagingListViewModel model)
    {
        if (await AppService.SubmitReviewAsync(model.Id))
        {
            await MessageService.Success(ShowFunctionSimpleName + "提交成功！", 1.5);
            await RefreshPagingListAsync();
        }
    }

    protected async Task OnDeleteActionClickAsync(TPagingListViewModel model)
    {
        if (await AppService.DeleteAsync(model.Id))
        {
            await MessageService.Success(ShowFunctionSimpleName + "删除成功！", 1.5);
            await RefreshPagingListAsync();
        }
    }

    protected async Task OnSaveCreateActionClickAsync(TPagingListViewModel model)
    {
        if (model is IEditingInRow e)
        {
            e.IsSaving = true;
            await AppService.CreateAsync(CreateInRowModel);
            await MessageService.Success(ShowFunctionSimpleName + "创建成功", 1.5);
            await RefreshPagingListAsync();
        }
    }

    protected async Task OnCancelCreateActionClickAsync(TPagingListViewModel model)
    {
        if (model is IEditingInRow e)
        {
            e.IsCreating = false;
            if (DataSource is List<TPagingListViewModel> l)
            {
                l.Remove(model);
            }
        }
        await Task.CompletedTask;
    }

    protected async Task OnSaveUpdateActionClickAsync(TPagingListViewModel model)
    {
        if (model is IEditingInRow e)
        {
            e.IsSaving = true;
            await AppService.UpdateAsync(model.Id, UpdateInRowModel);
            await MessageService.Success(ShowFunctionSimpleName + "修改成功", 1.5);
            await RefreshPagingListAsync();
        }
    }

    protected async Task OnCancelUpdateActionClickAsync(TPagingListViewModel model)
    {
        if (model is IEditingInRow e)
        {
            e.IsUpdating = false;
        }
        await Task.CompletedTask;
    }

    protected async Task OnUploadCompletedAsync(UploadInfo fileinfo)
    {
        if (fileinfo.File.State == UploadState.Fail)
        {
            await MessageService.Error("导入数据失败", 2);
        }
        else if (fileinfo.File.State == UploadState.Success)
        {
            await MessageService.Success("导入数据成功", 2);
            await RefreshPagingListAsync();
        }
    }

    public async Task OnToggleEnableChangedAsync(TPagingListViewModel model, bool isEnabled)
    {
        if (await AppService.ToggleEnabledAsync(model.Id, isEnabled))
        {
            await MessageService.Success(ShowFunctionSimpleName + (isEnabled ? "启用" : "禁用") + "成功！", 1.5);
            await RefreshPagingListAsync();
        }
        else
        {
            await MessageService.Error(ShowFunctionSimpleName + (isEnabled ? "启用" : "禁用") + "失败！", 1.5);
            if (model is IHasEnabled e)
            {
                e.IsEnabled = !isEnabled;
            }
            else
            {
                await RefreshPagingListAsync();
            }
        }
    }
}
